/**
 * @file meetings.py
 * @brief Meeting-related API routes for Meeting Management System.
 * @author Ziyi Wang
 *
 * Provides meeting creation, conflict detection, query, update, cancel, participant management, and filtering endpoints.
 */
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.orm import Session
from typing import List
from datetime import datetime
from sqlalchemy import and_, or_, func

from ..database import get_db
from ..models.schemas import Meeting, MeetingCreate, MeetingUpdate
from ..models.models import Meeting as MeetingModel
from ..models.models import User as UserModel
from ..models.models import Room as RoomModel
from ..auth import get_current_active_user

router = APIRouter(
    prefix="/api/meetings",
    tags=["meetings"],
    responses={404: {"description": "Not found"}},
)

/**
 * @brief Create a new meeting.
 * @param meeting MeetingCreate schema
 * @param db Database session
 * @param current_user Current user
 * @return Created meeting
 * @exception HTTPException 404 if room not found, 400 if time conflict
 */
@router.post("/", response_model=Meeting, status_code=status.HTTP_201_CREATED)
def create_meeting(
    meeting: MeetingCreate, 
    db: Session = Depends(get_db), 
    current_user: UserModel = Depends(get_current_active_user)
):
    # 检查会议室是否存在
    room = db.query(RoomModel).filter(RoomModel.id == meeting.room_id, RoomModel.is_active == True).first()
    if not room:
        raise HTTPException(status_code=404, detail="会议室不存在或不可用")
    
    # 检查时间冲突
    overlapping_meetings = db.query(MeetingModel).filter(
        MeetingModel.room_id == meeting.room_id,
        MeetingModel.is_cancelled == False,
        or_(
            and_(
                MeetingModel.start_time <= meeting.start_time,
                MeetingModel.end_time > meeting.start_time
            ),
            and_(
                MeetingModel.start_time < meeting.end_time,
                MeetingModel.end_time >= meeting.end_time
            ),
            and_(
                MeetingModel.start_time >= meeting.start_time,
                MeetingModel.end_time <= meeting.end_time
            )
        )
    ).all()
    
    if overlapping_meetings:
        raise HTTPException(status_code=400, detail="该时间段会议室已被预订")
    
    # 创建会议
    db_meeting = MeetingModel(
        title=meeting.title,
        description=meeting.description,
        start_time=meeting.start_time,
        end_time=meeting.end_time,
        room_id=meeting.room_id,
        owner_id=current_user.id
    )
    db.add(db_meeting)
    db.commit()
    db.refresh(db_meeting)
    
    # 添加参与者
    if meeting.participant_ids:
        participants = db.query(UserModel).filter(
            UserModel.id.in_(meeting.participant_ids),
            UserModel.is_active == True
        ).all()
        
        for participant in participants:
            db_meeting.participants.append(participant)
        
    # 始终将创建者添加为参与者
    if current_user not in db_meeting.participants:
        db_meeting.participants.append(current_user)
    
    db.commit()
    db.refresh(db_meeting)
    return db_meeting

/**
 * @brief Get all meetings (with filters and pagination).
 * @param skip Offset
 * @param limit Limit
 * @param db Database session
 * @param current_user Current user
 * @param start_date Filter by start date
 * @param end_date Filter by end date
 * @param room_id Filter by room
 * @param show_cancelled Show cancelled meetings
 * @return List of meetings and total count
 */
@router.get("/", response_model=None)
def read_meetings(
    skip: int = 0, 
    limit: int = 100, 
    db: Session = Depends(get_db), 
    current_user: UserModel = Depends(get_current_active_user),
    start_date: datetime = None,
    end_date: datetime = None,
    room_id: int = None,
    show_cancelled: bool = Query(False, description="是否显示已取消的会议")
):
    query = db.query(MeetingModel)
    
    # 筛选条件
    if not show_cancelled:
        query = query.filter(MeetingModel.is_cancelled == False)
        
    if start_date:
        query = query.filter(MeetingModel.start_time >= start_date)
        
    if end_date:
        query = query.filter(MeetingModel.end_time <= end_date)
        
    if room_id:
        query = query.filter(MeetingModel.room_id == room_id)
    
    # 获取总数
    total = query.count()
    
    # 分页获取会议
    meetings = query.order_by(MeetingModel.start_time.desc()).offset(skip).limit(limit).all()
    
    # 转换为字典列表，以便添加额外信息
    meetings_list = []
    for meeting in meetings:
        meeting_dict = {
            "id": meeting.id,
            "title": meeting.title,
            "description": meeting.description,
            "start_time": meeting.start_time,
            "end_time": meeting.end_time,
            "is_cancelled": meeting.is_cancelled,
            "created_at": meeting.created_at,
            "room_id": meeting.room_id,
            "owner_id": meeting.owner_id,
            
            # 添加关联信息
            "room": {
                "id": meeting.room.id,
                "name": meeting.room.name
            } if meeting.room else None,
            
            "owner": {
                "id": meeting.owner.id,
                "username": meeting.owner.username
            } if meeting.owner else None,
        }
        
        # 添加易读的字段
        meeting_dict["room_name"] = meeting.room.name if meeting.room else "未知会议室"
        meeting_dict["owner_name"] = meeting.owner.username if meeting.owner else "未知用户"
        
        meetings_list.append(meeting_dict)
    
    # 返回带有分页信息的结构化响应
    return {
        "meetings": meetings_list,
        "total": total,
        "has_more": total > skip + limit
    }

/**
 * @brief Get meetings created or participated by current user.
 * @param skip Offset
 * @param limit Limit
 * @param db Database session
 * @param current_user Current user
 * @param start_date Filter by start date
 * @param end_date Filter by end date
 * @param show_cancelled Show cancelled meetings
 * @return List of meetings
 */
@router.get("/my-meetings", response_model=List[Meeting])
def read_my_meetings(
    skip: int = 0, 
    limit: int = 100, 
    db: Session = Depends(get_db), 
    current_user: UserModel = Depends(get_current_active_user),
    start_date: datetime = None,
    end_date: datetime = None,
    show_cancelled: bool = Query(False, description="是否显示已取消的会议")
):
    # 查询用户创建或参与的会议
    query = db.query(MeetingModel).filter(
        or_(
            MeetingModel.owner_id == current_user.id,
            MeetingModel.participants.any(UserModel.id == current_user.id)
        )
    )
    
    # 筛选条件
    if not show_cancelled:
        query = query.filter(MeetingModel.is_cancelled == False)
        
    if start_date:
        query = query.filter(MeetingModel.start_time >= start_date)
        
    if end_date:
        query = query.filter(MeetingModel.end_time <= end_date)
    
    meetings = query.offset(skip).limit(limit).all()
    return meetings

/**
 * @brief Get a specific meeting by ID.
 * @param meeting_id Meeting ID
 * @param db Database session
 * @param current_user Current user
 * @return Meeting info
 * @exception HTTPException 404 if not found
 */
@router.get("/{meeting_id}", response_model=Meeting)
def read_meeting(
    meeting_id: int, 
    db: Session = Depends(get_db), 
    current_user: UserModel = Depends(get_current_active_user)
):
    db_meeting = db.query(MeetingModel).filter(MeetingModel.id == meeting_id).first()
    if db_meeting is None:
        raise HTTPException(status_code=404, detail="会议不存在")
    return db_meeting

/**
 * @brief Update meeting info.
 * @param meeting_id Meeting ID
 * @param meeting MeetingUpdate schema
 * @param db Database session
 * @param current_user Current user
 * @return Updated meeting
 * @exception HTTPException 404 if not found, 403 if no permission, 400 if time conflict
 */
@router.put("/{meeting_id}", response_model=Meeting)
def update_meeting(
    meeting_id: int, 
    meeting: MeetingUpdate, 
    db: Session = Depends(get_db), 
    current_user: UserModel = Depends(get_current_active_user)
):
    db_meeting = db.query(MeetingModel).filter(MeetingModel.id == meeting_id).first()
    if db_meeting is None:
        raise HTTPException(status_code=404, detail="会议不存在")
    
    # 检查权限：只有会议创建者可以修改
    if db_meeting.owner_id != current_user.id:
        raise HTTPException(status_code=403, detail="没有权限修改此会议")
    
    # 如果修改了时间或会议室，检查冲突
    if (meeting.start_time or meeting.end_time or meeting.room_id) and not db_meeting.is_cancelled:
        start_time = meeting.start_time if meeting.start_time else db_meeting.start_time
        end_time = meeting.end_time if meeting.end_time else db_meeting.end_time
        room_id = meeting.room_id if meeting.room_id else db_meeting.room_id
        
        # 检查会议室是否存在
        if meeting.room_id:
            room = db.query(RoomModel).filter(RoomModel.id == room_id, RoomModel.is_active == True).first()
            if not room:
                raise HTTPException(status_code=404, detail="会议室不存在或不可用")
        
        # 检查时间冲突
        overlapping_meetings = db.query(MeetingModel).filter(
            MeetingModel.id != meeting_id,
            MeetingModel.room_id == room_id,
            MeetingModel.is_cancelled == False,
            or_(
                and_(
                    MeetingModel.start_time <= start_time,
                    MeetingModel.end_time > start_time
                ),
                and_(
                    MeetingModel.start_time < end_time,
                    MeetingModel.end_time >= end_time
                ),
                and_(
                    MeetingModel.start_time >= start_time,
                    MeetingModel.end_time <= end_time
                )
            )
        ).all()
        
        if overlapping_meetings:
            raise HTTPException(status_code=400, detail="该时间段会议室已被预订")
    
    # 更新参与者
    if meeting.participant_ids is not None:
        # 清空现有参与者（除了创建者自己）
        for participant in db_meeting.participants:
            if participant.id != current_user.id:
                db_meeting.participants.remove(participant)
        
        # 添加新参与者
        participants = db.query(UserModel).filter(
            UserModel.id.in_(meeting.participant_ids),
            UserModel.is_active == True
        ).all()
        
        for participant in participants:
            if participant not in db_meeting.participants:
                db_meeting.participants.append(participant)
        
        # 确保创建者始终是参与者
        if current_user not in db_meeting.participants:
            db_meeting.participants.append(current_user)
    
    # 更新其他字段
    meeting_data = meeting.model_dump(exclude={"participant_ids"}, exclude_unset=True)
    for key, value in meeting_data.items():
        setattr(db_meeting, key, value)
    
    db.commit()
    db.refresh(db_meeting)
    return db_meeting

/**
 * @brief Cancel a meeting.
 * @param meeting_id Meeting ID
 * @param db Database session
 * @param current_user Current user
 * @return Cancelled meeting
 * @exception HTTPException 404 if not found, 403 if no permission
 */
@router.post("/{meeting_id}/cancel", response_model=Meeting)
def cancel_meeting(
    meeting_id: int, 
    db: Session = Depends(get_db), 
    current_user: UserModel = Depends(get_current_active_user)
):
    db_meeting = db.query(MeetingModel).filter(MeetingModel.id == meeting_id).first()
    if db_meeting is None:
        raise HTTPException(status_code=404, detail="会议不存在")
    
    # 检查权限：只有会议创建者可以取消
    if db_meeting.owner_id != current_user.id:
        raise HTTPException(status_code=403, detail="没有权限取消此会议")
    
    # 如果会议已取消，不能重复取消
    if db_meeting.is_cancelled:
        raise HTTPException(status_code=400, detail="会议已经被取消")
    
    db_meeting.is_cancelled = True
    db.commit()
    db.refresh(db_meeting)
    return db_meeting

/**
 * @brief Add a participant to a meeting.
 * @param meeting_id Meeting ID
 * @param user_id User ID
 * @param db Database session
 * @param current_user Current user
 * @return None
 * @exception HTTPException 404 if meeting/user not found, 403 if no permission
 */
@router.post("/{meeting_id}/participants/{user_id}", status_code=status.HTTP_204_NO_CONTENT)
def add_participant(
    meeting_id: int,
    user_id: int,
    db: Session = Depends(get_db),
    current_user: UserModel = Depends(get_current_active_user)
):
    db_meeting = db.query(MeetingModel).filter(MeetingModel.id == meeting_id).first()
    if db_meeting is None:
        raise HTTPException(status_code=404, detail="会议不存在")
    
    # 检查权限：只有会议创建者可以添加参与者
    if db_meeting.owner_id != current_user.id:
        raise HTTPException(status_code=403, detail="没有权限修改此会议的参与者")
    
    user = db.query(UserModel).filter(UserModel.id == user_id, UserModel.is_active == True).first()
    if user is None:
        raise HTTPException(status_code=404, detail="用户不存在或已停用")
    
    # 检查是否已经是参与者
    if user in db_meeting.participants:
        return None
    
    db_meeting.participants.append(user)
    db.commit()
    return None

/**
 * @brief Remove a participant from a meeting.
 * @param meeting_id Meeting ID
 * @param user_id User ID
 * @param db Database session
 * @param current_user Current user
 * @return None
 * @exception HTTPException 404 if meeting/user not found, 403 if no permission
 */
@router.delete("/{meeting_id}/participants/{user_id}", status_code=status.HTTP_204_NO_CONTENT)
def remove_participant(
    meeting_id: int,
    user_id: int,
    db: Session = Depends(get_db),
    current_user: UserModel = Depends(get_current_active_user)
):
    db_meeting = db.query(MeetingModel).filter(MeetingModel.id == meeting_id).first()
    if db_meeting is None:
        raise HTTPException(status_code=404, detail="会议不存在")
    
    # 检查权限：只有会议创建者可以移除参与者
    if db_meeting.owner_id != current_user.id:
        raise HTTPException(status_code=403, detail="没有权限修改此会议的参与者")
    
    # 不能移除创建者自己
    if user_id == current_user.id:
        raise HTTPException(status_code=400, detail="创建者不能从会议中移除自己")
    
    user = db.query(UserModel).filter(UserModel.id == user_id).first()
    if user is None:
        raise HTTPException(status_code=404, detail="用户不存在")
    
    # 检查是否是参与者
    if user not in db_meeting.participants:
        return None
    
    db_meeting.participants.remove(user)
    db.commit()
    return None

/**
 * @brief Get all meetings for a specific room.
 * @param room_id Room ID
 * @param skip Offset
 * @param limit Limit
 * @param db Database session
 * @param current_user Current user
 * @param start_date Filter by start date
 * @param end_date Filter by end date
 * @param show_cancelled Show cancelled meetings
 * @return List of meetings
 */
@router.get("/room/{room_id}", response_model=List[Meeting])
def read_room_meetings(
    room_id: int,
    skip: int = 0, 
    limit: int = 100, 
    db: Session = Depends(get_db), 
    current_user: UserModel = Depends(get_current_active_user),
    start_date: datetime = None,
    end_date: datetime = None,
    show_cancelled: bool = Query(False, description="是否显示已取消的会议")
):
    # 检查会议室是否存在
    room = db.query(RoomModel).filter(RoomModel.id == room_id).first()
    if not room:
        raise HTTPException(status_code=404, detail="会议室不存在")
        
    # 查询会议室的会议
    query = db.query(MeetingModel).filter(MeetingModel.room_id == room_id)
    
    # 筛选条件
    if not show_cancelled:
        query = query.filter(MeetingModel.is_cancelled == False)
        
    if start_date:
        query = query.filter(MeetingModel.start_time >= start_date)
        
    if end_date:
        query = query.filter(MeetingModel.end_time <= end_date)
    
    # 按开始时间排序
    query = query.order_by(MeetingModel.start_time)
    
    meetings = query.offset(skip).limit(limit).all()
    return meetings